// -*-mode:c++; coding:utf-8-*-

#ifndef _XBASE_INTRUSIVE_PTR_HELPER_HPP_
#define _XBASE_INTRUSIVE_PTR_HELPER_HPP_

#include "atomic.h"

namespace xbase
{

	struct reference_counter
	{
		atomic_t m_counter;
		reference_counter() { atomic_set(&m_counter, 0); }
		void inc() { atomic_inc(&m_counter); }
		int dec_and_test() { return atomic_dec_and_test(&m_counter); }
	};

	// 
	// self-managed ptr
	// 
	// usage:
	//
	// class sharable_car
	// {
	// private:
	//   typedef std::allocator_type allocator_type;
	//   typedef basic_factory<sharable_car> factory;
	// private:
	//   reference_counter m_counter;
	//   INTRUSIVE_PTR_HOOKS(sharable_car, /*class name*/
	//                       m_counter,    /*counter name*/
	//                       factory);     /*manager class name*/
	// };

#define INTRUSIVE_PTR_HOOKS(class_name, counter, factory)	\
	friend inline						\
	void intrusive_ptr_add_ref(class_name *p) {		\
		p->class_name::counter.inc();			\
	}							\
								\
	friend inline						\
	void intrusive_ptr_release(class_name *p) {		\
		if(p->class_name::counter.dec_and_test())	\
		{						\
			class_name::factory::destroy(p);	\
		}						\
	}

} // namespace xbase

#endif	// _XBASE_INTRUSIVE_PTR_HELPER_HPP_
